package gwt.immunology.client.view;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.logical.shared.ShowRangeEvent;
import com.google.gwt.event.logical.shared.ShowRangeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.datepicker.client.CalendarUtil;
import gwt.immunology.client.components.CustomBox;
import gwt.immunology.client.components.DateBoxEx;
import gwt.immunology.client.components.DatePickerEx;
import gwt.immunology.client.i18n.ImmunologyI18N;
import gwt.immunology.shared.GenericDto;
import gwt.immunology.shared.enums.GenderEnum;

import java.util.Date;

import static gwt.immunology.shared.GenericDtoKeys.*;
import static gwt.immunology.shared.utils.ImmunologyUtils.DD_MM_YYYY;

public class SearchPatientsViewImpl extends Composite implements SearchPatientsView {
    private Presenter presenter;
    private static SearchPatientsViewImplUiBinder uiBinder = GWT.create(SearchPatientsViewImplUiBinder.class);
    private DateTimeFormat dateFormatter = DateTimeFormat.getFormat(DD_MM_YYYY);
    private Date birthdayMaxDate;
    private Date birthdayMinDate;
    private Date registerMaxDate;
    private Date registerMinDate;

    interface SearchPatientsViewImplUiBinder extends UiBinder<Widget, SearchPatientsViewImpl> {
    }

    ImmunologyI18N i18n = GWT.create(ImmunologyI18N.class);

    public SearchPatientsViewImpl() {
	initWidget(uiBinder.createAndBindUi(this));
	birthdayFrom.addValueChangeHandler(new ValueChangeHandler<Date>() {
	    @Override
	    public void onValueChange(ValueChangeEvent<Date> event) {
		birthdayMinDate = event.getValue();
	    }
	});

	birthdayTo.addValueChangeHandler(new ValueChangeHandler<Date>() {
	    @Override
	    public void onValueChange(ValueChangeEvent<Date> event) {
		birthdayMaxDate = event.getValue();
	    }
	});

	registerFrom.addValueChangeHandler(new ValueChangeHandler<Date>() {
	    @Override
	    public void onValueChange(ValueChangeEvent<Date> event) {
		registerMinDate = event.getValue();
	    }
	});

	registerTo.addValueChangeHandler(new ValueChangeHandler<Date>() {
	    @Override
	    public void onValueChange(ValueChangeEvent<Date> event) {
		registerMaxDate = event.getValue();
	    }
	});

	birthdayTo.getDatePicker().addShowRangeHandler(new ShowRangeHandler<Date>() {
	    @Override
	    public void onShowRange(ShowRangeEvent<Date> dateShowRangeEvent) {
		Date start = dateShowRangeEvent.getStart();
		Date end = dateShowRangeEvent.getEnd();
		Integer daysBetween = CalendarUtil.getDaysBetween(start, end);
		Date currentDate = new Date();
		if (birthdayMinDate != null) {
		    for (int i = 0; i < daysBetween; i++) {
			Date date = new Date(start.getTime());
			Boolean enabled = true;
			CalendarUtil.addDaysToDate(date, i);
			String dateString = dateFormatter.format(date);
			Date dateFormatted = dateFormatter.parse(dateString);
			String minDateString = dateFormatter.format(birthdayMinDate);
			Date minDateFormatted = dateFormatter.parse(minDateString);
			String currentDateString = dateFormatter.format(currentDate);
			Date currentDateFormatted = dateFormatter.parse(currentDateString);

			if (dateFormatted.after(currentDateFormatted) || dateFormatted.before(minDateFormatted)) {
			    enabled = false;
			}
			birthdayTo.getDatePicker().getCalendarView().setEnabledOnDate(enabled, date);
		    }
		} else {
		    for (int i = 0; i < daysBetween; i++) {
			Date date = new Date(start.getTime());
			Boolean enabled = true;
			CalendarUtil.addDaysToDate(date, i);
			String dateString = dateFormatter.format(date);
			Date dateFormatted = dateFormatter.parse(dateString);
			String currentDateString = dateFormatter.format(currentDate);
			Date currentDateFormatted = dateFormatter.parse(currentDateString);

			if (dateFormatted.after(currentDateFormatted)) {
			    enabled = false;
			}
			birthdayTo.getDatePicker().getCalendarView().setEnabledOnDate(enabled, date);
		    }
		}
	    }
	});

	birthdayFrom.getDatePicker().addShowRangeHandler(new ShowRangeHandler<Date>() {
	    @Override
	    public void onShowRange(ShowRangeEvent<Date> dateShowRangeEvent) {
		Date start = dateShowRangeEvent.getStart();
		Date end = dateShowRangeEvent.getEnd();
		Integer daysBetween = CalendarUtil.getDaysBetween(start, end);
		Date currentDate = new Date();
		if (birthdayMaxDate != null) {
		    for (int i = 0; i < daysBetween; i++) {
			Date date = new Date(start.getTime());
			Boolean enabled = true;
			CalendarUtil.addDaysToDate(date, i);
			String dateString = dateFormatter.format(date);
			Date dateFormatted = dateFormatter.parse(dateString);
			String maxDateString = dateFormatter.format(birthdayMaxDate);
			Date maxDateFormatted = dateFormatter.parse(maxDateString);
			String currentDateString = dateFormatter.format(currentDate);
			Date currentDateFormatted = dateFormatter.parse(currentDateString);

			if (dateFormatted.after(currentDateFormatted) || dateFormatted.after(maxDateFormatted)) {
			    enabled = false;
			}
			birthdayFrom.getDatePicker().getCalendarView().setEnabledOnDate(enabled, date);
		    }
		} else {
		    for (int i = 0; i < daysBetween; i++) {
			Date date = new Date(start.getTime());
			Boolean enabled = true;
			CalendarUtil.addDaysToDate(date, i);
			String dateString = dateFormatter.format(date);
			Date dateFormatted = dateFormatter.parse(dateString);
			String currentDateString = dateFormatter.format(currentDate);
			Date currentDateFormatted = dateFormatter.parse(currentDateString);

			if (dateFormatted.after(currentDateFormatted)) {
			    enabled = false;
			}
			birthdayFrom.getDatePicker().getCalendarView().setEnabledOnDate(enabled, date);
		    }
		}
	    }
	});

	registerTo.getDatePicker().addShowRangeHandler(new ShowRangeHandler<Date>() {
	    @Override
	    public void onShowRange(ShowRangeEvent<Date> dateShowRangeEvent) {
		Date start = dateShowRangeEvent.getStart();
		Date end = dateShowRangeEvent.getEnd();
		Integer daysBetween = CalendarUtil.getDaysBetween(start, end);
		Date currentDate = new Date();
		if (registerMinDate != null) {
		    for (int i = 0; i < daysBetween; i++) {
			Date date = new Date(start.getTime());
			Boolean enabled = true;
			CalendarUtil.addDaysToDate(date, i);
			String dateString = dateFormatter.format(date);
			Date dateFormatted = dateFormatter.parse(dateString);
			String minDateString = dateFormatter.format(registerMinDate);
			Date minDateFormatted = dateFormatter.parse(minDateString);
			String currentDateString = dateFormatter.format(currentDate);
			Date currentDateFormatted = dateFormatter.parse(currentDateString);

			if (dateFormatted.after(currentDateFormatted) || dateFormatted.before(minDateFormatted)) {
			    enabled = false;
			}
			registerTo.getDatePicker().getCalendarView().setEnabledOnDate(enabled, date);
		    }
		} else {
		    for (int i = 0; i < daysBetween; i++) {
			Date date = new Date(start.getTime());
			Boolean enabled = true;
			CalendarUtil.addDaysToDate(date, i);
			String dateString = dateFormatter.format(date);
			Date dateFormatted = dateFormatter.parse(dateString);
			String currentDateString = dateFormatter.format(currentDate);
			Date currentDateFormatted = dateFormatter.parse(currentDateString);

			if (dateFormatted.after(currentDateFormatted)) {
			    enabled = false;
			}
			registerTo.getDatePicker().getCalendarView().setEnabledOnDate(enabled, date);
		    }
		}
	    }
	});

	registerFrom.getDatePicker().addShowRangeHandler(new ShowRangeHandler<Date>() {
	    @Override
	    public void onShowRange(ShowRangeEvent<Date> dateShowRangeEvent) {
		Date start = dateShowRangeEvent.getStart();
		Date end = dateShowRangeEvent.getEnd();
		Integer daysBetween = CalendarUtil.getDaysBetween(start, end);
		Date currentDate = new Date();
		if (registerMaxDate != null) {
		    for (int i = 0; i < daysBetween; i++) {
			Date date = new Date(start.getTime());
			Boolean enabled = true;
			CalendarUtil.addDaysToDate(date, i);
			String dateString = dateFormatter.format(date);
			Date dateFormatted = dateFormatter.parse(dateString);
			String maxDateString = dateFormatter.format(registerMaxDate);
			Date maxDateFormatted = dateFormatter.parse(maxDateString);
			String currentDateString = dateFormatter.format(currentDate);
			Date currentDateFormatted = dateFormatter.parse(currentDateString);

			if (dateFormatted.after(currentDateFormatted) || dateFormatted.after(maxDateFormatted)) {
			    enabled = false;
			}
			registerFrom.getDatePicker().getCalendarView().setEnabledOnDate(enabled, date);
		    }
		} else {
		    for (int i = 0; i < daysBetween; i++) {
			Date date = new Date(start.getTime());
			Boolean enabled = true;
			CalendarUtil.addDaysToDate(date, i);
			String dateString = dateFormatter.format(date);
			Date dateFormatted = dateFormatter.parse(dateString);
			String currentDateString = dateFormatter.format(currentDate);
			Date currentDateFormatted = dateFormatter.parse(currentDateString);

			if (dateFormatted.after(currentDateFormatted)) {
			    enabled = false;
			}
			registerFrom.getDatePicker().getCalendarView().setEnabledOnDate(enabled, date);
		    }
		}
	    }
	});
    }

    @UiField
    public CustomBox customBox;
    @UiField
    public TextBox patientLastName;
    @UiField
    public TextBox patientFirstName;
    @UiField
    public TextBox patientMiddleName;
    @UiField
    public RadioButton genderMale;
    @UiField
    public RadioButton genderFemale;
    @UiField
    public DateBoxEx birthdayFrom;
    @UiField
    public DateBoxEx birthdayTo;
    @UiField
    public DateBoxEx registerFrom;
    @UiField
    public DateBoxEx registerTo;
    @UiField
    public TextBox country;
    @UiField
    public TextBox region;
    @UiField
    public TextBox district;
    @UiField
    public TextBox city;
    @UiField
    public TextBox street;
    @UiField
    public TextBox house;
    @UiField
    public TextBox flat;
    @UiField
    public Button buttonSearch;
    @UiField
    public Button buttonReset;

    @UiFactory
    DateBoxEx initDateBox() {
	return new DateBoxEx(new DatePickerEx());
    }

    @UiHandler("buttonReset")
    void resetButtonClick(ClickEvent e) {
	this.patientLastName.setText("");
	this.patientFirstName.setText("");
	this.patientMiddleName.setText("");
	this.genderMale.setValue(false);
	this.genderFemale.setValue(false);
	resetDateBoxes();
	this.country.setText("");
	this.region.setText("");
	this.district.setText("");
	this.city.setText("");
	this.street.setText("");
	this.house.setText("");
	this.flat.setText("");
    }

    private void resetDateBoxes() {
	this.birthdayFrom.reset();
	this.birthdayTo.reset();
	this.registerFrom.reset();
	this.registerTo.reset();
	this.birthdayMinDate = null;
	this.birthdayMaxDate = null;
	this.registerMinDate = null;
	this.registerMaxDate = null;
    }

    @UiHandler("buttonSearch")
    void searchButtonClick(ClickEvent e) {
	GenericDto searchCriteria = new GenericDto();
	if (!this.patientLastName.getText().trim().isEmpty()) {
	    searchCriteria.put(LAST_NAME, this.patientLastName.getText().trim());
	}

	if (!this.patientFirstName.getText().trim().isEmpty()) {
	    searchCriteria.put(FIRST_NAME, this.patientFirstName.getText().trim());
	}

	if (!this.patientMiddleName.getText().trim().isEmpty()) {
	    searchCriteria.put(MIDDLE_NAME, this.patientMiddleName.getText().trim());
	}

	if (this.genderFemale.getValue()) {
	    searchCriteria.put(GENDER, GenderEnum.FEMALE.toString());
	} else if (this.genderMale.getValue()) {
	    searchCriteria.put(GENDER, GenderEnum.MALE.toString());
	}else{
	    
	}

	if (!this.country.getText().trim().isEmpty()) {
	    searchCriteria.put(COUNTRY, this.country.getText().trim());
	}

	if (!this.region.getText().trim().isEmpty()) {
	    searchCriteria.put(REGION, this.region.getText().trim());
	}

	if (!this.district.getText().trim().isEmpty()) {
	    searchCriteria.put(DISTRICT, this.district.getText().trim());
	}

	if (!this.city.getText().trim().isEmpty()) {
	    searchCriteria.put(CITY, this.city.getText().trim());
	}

	if (!this.street.getText().trim().isEmpty()) {
	    searchCriteria.put(STREET, this.street.getText().trim());
	}

	if (!this.house.getText().trim().isEmpty()) {
	    searchCriteria.put(HOUSE, this.house.getText().trim());
	}

	if (!this.flat.getText().trim().isEmpty()) {
	    searchCriteria.put(FLAT, new Integer(this.flat.getText().trim()));
	}

	if (this.birthdayFrom.getValue() != null) {
	    searchCriteria.put(BIRTHDAY_FROM, this.birthdayFrom.getValue());
	}

	if (this.birthdayTo.getValue() != null) {
	    searchCriteria.put(BIRTHDAY_TO, this.birthdayTo.getValue());
	}

	if (this.registerFrom.getValue() != null) {
	    searchCriteria.put(REGISTRATION_FROM, this.registerFrom.getValue());
	}

	if (this.registerTo.getValue() != null) {
	    searchCriteria.put(REGISTRATION_TO, this.registerTo.getValue());
	}

	if (searchCriteria.isEmpty()) {
	    Window.alert(i18n.requiredFieldsMessage());
	} else {
	    presenter.findPatients(searchCriteria);
	}
    }

    @Override
    public void setPresenter(Presenter presenter) {
	this.presenter = presenter;
    }

}
